package model.viewModels;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import model.Board;
import model.Match;
import model.Move;
import view.ChessFrame;
import view.viewPanels.ActGamesViewPanel;
import control.Communication;

/**
 * model-class for the actGames-view
 */
public class ActGamesModel {

    /**
     * related view class
     */
    private ActGamesViewPanel actGamesViewPanel;

    /**
     * List of all actual matches
     */
    private ArrayList<Match> actMatches;

    /**
     * List of all actual matches where it is the logged in user's turn
     */
    private ArrayList<Match> actYourTurnMatches;

    /**
     * the actual match
     */
    private Match actualMatch;

    /**
     * the board class reference for the chess logic
     */
    // TODO wird nicht benutzt
    private Board board;

    /**
     * constructor of the ActGamesModel
     * 
     * @param actGamesView
     *            the related view class
     */
    public ActGamesModel( ActGamesViewPanel actGamesView )
    {
	this.actGamesViewPanel = actGamesView;
	this.board = new Board( this.actualMatch );
    }

    /**
     * updates the match lists on login and every 5 minutes
     */
    public final void updateActMatchData()
    {
	this.actMatches = ChessFrame.centerViewPanel.getCenterModel().getActMatches();
	this.actYourTurnMatches = ChessFrame.centerViewPanel.getCenterModel().getActYourTurnMatches();

	yourTurnAction();
    }

    /**
     * changes the actGames-table, switches between actMatches and actYourTurnMatches
     */
    public final void yourTurnAction()
    {
	boolean yourTurn = this.actGamesViewPanel.getCbYourTurn().isSelected();
	if ( yourTurn )
	{
	    this.actGamesViewPanel.updateMatchTable( this.actYourTurnMatches );
	}
	else
	{
	    this.actGamesViewPanel.updateMatchTable( this.actMatches );
	}
    }

    /**
     * invoked when the playing field is clicked, recieves a point with coordinates on the playing field and the field
     * size
     * 
     * @param click
     *            the click coordinates on the playing field
     * @param fieldsize
     *            the size of a field on the playing field
     */
    public final void boardClickedAction( Point click, int fieldsize )
    {
	StringBuilder pos = new StringBuilder();
	pos.append( (char)( 'A' + click.x / fieldsize ) );
	pos.append( 8 - click.y / fieldsize );
	System.out.println( pos.toString() );

	if ( this.actualMatch != null )
	{
	    // handle the click in the actual match and check if an update is necessary
	    if ( this.actualMatch.positionClickedAction( pos.toString() ) )
	    {
		int selectedMatch = this.actGamesViewPanel.getCtActGames().getSelected();
		ChessFrame.updateAction();
		this.actGamesViewPanel.getCtActGames().setSelectedExternal( selectedMatch );
	    }
	}
    }

    /**
     * getter of a single match by index, where it is the logged in players turn
     * 
     * @param matchIndex
     *            the match index as int
     * @return the match with the given index
     */
    // TODO currently not used
    public final Match getActYourTurnMatch( int matchIndex )
    {
	for ( Match m : this.actYourTurnMatches )
	{
	    if ( m.getId() == matchIndex ) { return m; }
	}
	return null;
    }

    /**
     * getter of a single match by index
     * 
     * @param matchIndex
     *            the match index as int
     * @return the math with the given index
     */
    // TODO currently not used
    public final Match getActMatch( int matchIndex )
    {
	for ( Match m : this.actMatches )
	{
	    if ( m.getId() == matchIndex ) { return m; }
	}
	return null;
    }

    /**
     * sets the actual match attribute
     * 
     * @param selected
     *            the selected row in actGames table
     * @param yourTurn
     *            true if the actual match is in the yourTurnMatch list, false if it is in the normal match list
     */
    public final void setActualMatch( int selected, boolean yourTurn )
    {
	if ( this.actualMatch != null )
	{
	    this.actualMatch.resetFigureSelection();
	}

	if ( yourTurn )
	{
	    this.actualMatch = this.actYourTurnMatches.get( selected );
	}
	else
	{
	    this.actualMatch = this.actMatches.get( selected );

	}

	loadActMoves();
    }

    /**
     * load the moves for the actual match
     */
    private void loadActMoves()
    {
	// get move data
	String[] moveData = Communication.getActMoves( this.actualMatch.getId(), CenterModel.loggedInUser.getNick() );

	// build move list
	List<Move> moves = new ArrayList<Move>();
	String[] data;
	Move move;
	String one = "1";
	for ( int i = 0; i < moveData.length; i++ )
	{
	    data = moveData[i].split( "#" );
	    move = new Move();
	    move.setNumber( Integer.valueOf( data[0] ) );
	    move.setDate( data[1] );
	    move.setStartField( data[2] );
	    move.setEndField( data[3] );
	    move.setCastling( data[4].equals( one ) );
	    move.setChecked( data[5].equals( one ) );
	    move.setCheckmate( data[6].equals( one ) );
	    move.setEnPassant( data[7].equals( one ) );
	    moves.add( move );
	}
	this.actualMatch.setMovesList( moves );
	this.actualMatch.updateFigurePositions();

	// prepare data for moves table
	String[][] values = new String[moves.size()][4];
	for ( int i = 0; i < values.length; i++ )
	{
	    values[i][0] = String.valueOf( moves.get( i ).getNumber() );
	    values[i][1] = moves.get( i ).getStartField() + " - " + moves.get( i ).getEndField();
	    values[i][2] = this.actualMatch.getActingPlayer( moves.get( i ).getNumber() );
	    values[i][3] = moves.get( i ).getFormattedDate();
	}

	// update moves table
	this.actGamesViewPanel.getCtMoves().updateValues( values );
	if ( values.length > 0 )
	{
	    this.actGamesViewPanel.getCtMoves().setSelectedExternal( 0 );
	}
    }

    /**
     * getter of actualMatch
     * 
     * @return the actualMatch
     */
    public final Match getActualMatch()
    {
	return this.actualMatch;
    }

    /**
     * getter of actGamesViewPanel
     * 
     * @return the actGamesViewPanel
     */
    public final ActGamesViewPanel getActGamesViewPanel()
    {
	return this.actGamesViewPanel;
    }

    /**
     * getter of actMatches
     * 
     * @return the actMatches
     */
    public final ArrayList<Match> getActMatches()
    {
	return this.actMatches;
    }

    /**
     * getter of actYourTurnMatches
     * 
     * @return the actYourTurnMatches
     */
    public final ArrayList<Match> getActYourTurnMatches()
    {
	return this.actYourTurnMatches;
    }

    /**
     * getter of boardModel
     * 
     * @return the boardModel
     */
    public final Board getBoardModel()
    {
	return this.board;
    }

}
